<?php
///////////////////////////////////////////////////////////////////////////////////////////////////////
//  这个文件是 JCAT PHP框架的一部，该项目和此文件 均遵循 GNU 自由软件协议
// 
//  Copyleft 2008 JeCat.cn(http://team.JeCat.cn)
//
//
//  JCAT PHP框架 的正式全名是：Jellicle Cat PHP Framework。
//  “Jellicle Cat”出自 Andrew Lloyd Webber的音乐剧《猫》（《Prologue:Jellicle Songs for Jellicle Cats》）。
//  JCAT 是一个开源项目，它像音乐剧中的猫一样自由，你可以毫无顾忌地使用JCAT PHP框架。JCAT 由中国团队开发维护。
//  正在使用的这个版本是：0.4.0 / SVN信息: $Id: class.JCAT_AccessRouter.php 1494 2009-03-19 12:53:43Z alee $
//
//
//
//  相关的链接：
//    [主页] http://jcat.JeCat.cn
//    [下载(HTTP)] http://code.google.com/p/jcat-php/downloads/list
//    [下载(svn)] svn checkout http://jcat-php.googlecode.com/svn/branches/0.4.0/Framework/ JCAT0.4
//    [在线文档] http://jcat.JeCat.cn/document
//    [社区] http://jj.jecat.cn/forum-7-1.html
//  不很相关：
//    [MP3] http://www.google.com/search?q=jellicle+songs+for+jellicle+cats+Andrew+Lloyd+Webber
//    [VCD/DVD] http://www.google.com/search?q=CAT+Andrew+Lloyd+Webber+video
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
/*-- Project Introduce --*/

class JCAT_AccessRouter
{
	/**
	 * Description
	 *
	 * @access	public
	 * @param	$sTopPath	
	 * @return	void
	 */
	public function JCAT_AccessRouter($sTopPath,$sAccessFilename=null)
	{
		if(!$sAccessFilename)
		{
			$sAccessFilename = self::$sDefaultAccessFilename ;
		}
		
		$this->sAccessFilePath = $sTopPath.'/'.$sAccessFilename ;
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @return	string
	 */
	public function GetAccessFilePath()
	{
		return $this->sAccessFilePath ;
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @static
	 * @return	JCAT_AccessRoute
	 */
	static public function GetRootRouter()
	{
		return new JCAT_AccessRouter(ROOT_PATH) ;
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @param	$aPathRule		JCAT_AccessRoutePath
	 * @return	void
	 */
	public function AddPathRule(JCAT_AccessRoutePath $aPathRule)
	{
		$this->arrPathRules[ $aPathRule->MakeKey() ] = $aPathRule ;
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @return	void
	 */
	public function AddPath(/* parameters .. ..*/)
	{
		$arrArgs = func_get_args() ;
		$sPath = array_shift($arrArgs) ;
		$aPath = new JCAT_AccessRoutePath($sPath) ;
		
		foreach ($arrArgs as $arrParam)
		{
			JCAT_ASSERT::ASSERT_(isset($arrParam[0]),JCAT_Language::SentenceEx('缺少必须的参数','JCAT',null)) ;
			$sPrefix = $arrParam[0] ;
			$sParamName = isset($arrParam[1])? $arrParam[1]: '' ;
			$sPostfix = isset($arrParam[2])? $arrParam[2]: '' ;
			
			$aPath->AddParameter($sPrefix,$sParamName,$sPostfix) ;
		}

		$this->AddPathRule( $aPath ) ;
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @return	void
	 */
	public function GetAccessUrl($sUrl)
	{
		$arrUrl = parse_url($sUrl) ;
		$arrParams = array() ;
		parse_str($arrUrl['query'],$arrParams) ;
		$arrParamNames = array_keys($arrParams) ;
		
		$sKey = JCAT_AccessRoutePath::MakeKeyFromParamNames($arrUrl['path'],$arrParamNames) ;
		
		if( isset($this->arrPathRules[$sKey]) )
		{
			return $this->arrPathRules[$sKey]->RewritePath($arrParams) ;
		}
		
		else
		{
			return $sUrl ;
		}
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @return	string
	 */
	public function MakeRewriteRules()
	{
		$arrRegExpLines = array() ;
		foreach ($this->arrPathRules as $aPathRule)
		{
			$arrRegExpLines[] = $aPathRule->MakePathRule("\t") ;
		}
		
		$sRegExp = implode("\r\n",$arrRegExpLines) ;
		$sRegExp = "
	RewriteEngine On	

	RewriteCond %{REQUEST_FILENAME} !-f
{$sRegExp}
" ;

		return $sRegExp ;
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @return	void
	 */
	public function SavePathRules()
	{
		$sRewriteRegExp = $this->MakeRewriteRules() ;

		if( !is_file($this->sAccessFilePath) )
		{
			JCAT_FSO::CreateFile($this->sAccessFilePath) ;
		}

		$sAccessFileContent = file_get_contents($this->sAccessFilePath) ;
		
		$nMarkStartPos = strpos($sAccessFileContent,self::ROUTE_RULE_MARK_START) ;
		if( $nMarkStartPos!==false )
		{
			$nMarkEndPos = strpos($sAccessFileContent,self::ROUTE_RULE_MARK_END) ;
			$nRulesStartPos = $nMarkStartPos + strlen(self::ROUTE_RULE_MARK_START) ;
			$nOldRulesLen = $nMarkEndPos - $nRulesStartPos ;
			
			$sAccessFileContent = substr_replace($sAccessFileContent,$sRewriteRegExp,$nRulesStartPos,$nOldRulesLen) ;
			file_put_contents($this->sAccessFilePath,$sAccessFileContent) ;
		}
		
		else
		{
			$sRewriteRegExp = "
<IfModule mod_rewrite.c>

	
	# -- Othar rules here --
	#  ... ...
	

".JCAT_Language::SentenceEx('## 以下内容由 JCAT_AccessRouter::SavePathRules() 方法自动维护， 任何手工修改都会被覆盖','JCAT',null)
					. "\r\n" . self::ROUTE_RULE_MARK_START.$sRewriteRegExp.self::ROUTE_RULE_MARK_END . "


</IfModule>" ;

			file_put_contents($this->sAccessFilePath,$sRewriteRegExp,FILE_APPEND) ;
		}
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @return	JCAT_IIterator
	 */
	public function CreatePathIterator()
	{
		return new JCAT_ArrayIterator($this->arrPathRules) ;
	}
	
	/**
	 * 根据 url 找到匹配的 JCAT_AccessRoutePath 对象
	 *
	 * @access	public
	 * @param	$sUrl		string
	 * @return	JCAT_AccessRoutePath
	 */
	public function FindPath($sUrl)
	{
		$aIterator = $this->CreatePathIterator() ;
		for ( $aIterator->First(); !$aIterator->IsDone(); $aIterator->Next() )
		{
			$aPathRule = $aIterator->Current() ;
			if( $aPathRule->Match($sUrl) )
			{
				return $aPathRule ;
			}
		}
		
		return null ;
	}
	
	
	
	const ROUTE_RULE_MARK_START = "####<<<<<<JCAT Route Rule Setting Start>>>>>>" ;
	const ROUTE_RULE_MARK_END = "####<<<<<<JCAT Route Rule Setting End>>>>>>" ;
	
	
	/**
	 * Description
	 * 
	 * @access	private
	 * @var		array
	 */
	private $arrPathRules = array() ;
	
	/**
	 * Description
	 * 
	 * @access	public
	 * @static
	 * @var		bool
	 */
	static public $bEnablePathRewrite = false ;
	
	/**
	 * Description
	 * 
	 * @access	public
	 * @static
	 * @var		bool
	 */
	static public $sDefaultAccessFilename = '.htaccess' ;
	
	/**
	 * Description
	 * 
	 * @access	private
	 * @var		string
	 */
	private $sAccessFilePath ;
	
	
}

/*
$aRootRouter = JCAT_AccessRouter::GetRootRouter() ;


# '/news/23/10524.html'  => '/index.php?controller=news&nClassId=23&nNewId=10524'
$aRootRouter->AddPath(
		'/index.php?controller=news' ,
		array('/news') ,
		array('/','nClassId') ,
		array('/','nNewId','.html') , 
) ;

*/
?>